Skip to main content

Processing Stages (MI.ProcessingStages)

Processing Stages

(MI.ProcessingStages)

The Processing Stages object sets the rules that are applied during a specific stage of the overall transaction: When the client request is received, before the request is sent to the origin, and before the response is sent to the client.

The following processing stage rules are supported by Qwilt CDN:

  • client-request: Defines actions to be taken upon receiving the client request. Currently this object can be used to:
    • Influence the origin selection.
    • Set conditions for rejecting or redirecting client requests based on header information (client request access).
  • origin-request: Modifies the request to the origin by manipulating the URI or headers of the request received from the client.
  • client-response: Modifies the client response by overriding the status code or manipulating the headers of the origin response.

For Processing Stage rules (MI.ProcessingStages), the inheritance logic applies to the entire set of rules as a single unit. That means:

  • If any Processing Stage rule is configured at the host level, it completely overrides all Processing Stage rules from the site level.
  • If any Processing Stage rule is configured at the path level, it completely overrides all Processing Stage rules from the host level.

For example, if the host configuration includes an On Client Request and an On Client Response rule, and the path configuration includes an On Origin Request rule, then only the On Origin Request rule is applied to the path. The host-level rules for Client Request and Client Response are not inherited by that path.

Example Structure

The following is an example illustrating the overall structure of the MI.ProcessingStages object when multiple stages and rules are configured. Note that each of the client-request, origin-request, and client-response objects are nested within the generic-metadata-value of the MI.ProcessingStages object.

We'll describe the specific configurations for each stage in the following sections.

{
"generic-metadata-type": "MI.ProcessingStages",
"generic-metadata-value": {
"client-request": [
{
"match": {
"expression": "req.h.user-agent ~= 'Mozilla'"
},
"stage-metadata": [
{
"generic-metadata": [
{
"generic-metadata-type": "MI.SourceMetadataExtended",
"generic-metadata-value": {
"sources": [
{
"protocol": "https/1.1",
"endpoints": [
"example.origin2.com"
]
}
]
}
}
]
}
]
},
{
"match": {
"expression": "req.h.MySecret != 'm1y2e3f4b5m6m7y9'"
},
"stage-metadata": [
{
"response-transform": {
"synthetic": {
"response-status": "403"
}
}
}
]
}
],
"origin-request": [
{
"stage-metadata": [
{
"request-transform": {
"headers": {
"add": [
{
"name": "x-cdn-processed",
"value": "true",
"value-is-expression": false
}
]
}
}
}
]
}
],
"client-response": [
{
"stage-metadata": [
{
"response-transform": {
"headers": {
"add": [
{
"name": "served-by",
"value": "qwilt-cdn",
"value-is-expression": false
}
]
}
}
}
]
}
]
}
}


client-request

Rules in this stage are evaluated when the CDN receives a request from the client. They are primarily used for origin selection and client request access based on criteria defined in a match expression.

Rules are defined using match conditions and stage metadata.

Origin Selection

You can use the client-request stage to direct certain client requests (e.g. based on user agent, headers, etc.) to an alternate origin. This is achieved by embedding an MI.SourceMetadataExtended object within the generic-metadata array inside stage-metadata.

Use a MEL condition in the match field to determine when this alternate origin should be used.

In this example, requests from a Mozilla user agent (the match condition) are directed to example.origin2.com.

Note the two nodes nested under client-request:

  • The MI.SourceMetadataExtended object defines the origin configuration. In this example, a single origin host is configured. However, you could also configure a failover or round-robin origin type.
  • The match field contains the MEL expression that sets the condition for directing a request to the alternate origin. In this example, the condition is if the user-agent is Mozilla.
{
"generic-metadata-type": "MI.ProcessingStages",
"generic-metadata-value": {
"client-request": [
{
"stage-metadata": [
{
"generic-metadata": [
{
"generic-metadata-type": "MI.SourceMetadataExtended",
"generic-metadata-value": {
"sources": [
{
"protocol": "https/1.1",
"endpoints": [
"example.origin2.com"
]
}
]
}
}
]
}
],
"match": {
"expression": "req.h.user-agent ~= 'Mozilla'"
}
}
]
}
}


Client Request Access

You can use the client-request stage to set conditions for rejecting or redirecting incoming client requests based on criteria in a match expression. For example, to block specific referrers, or require a secret header.

This is achieved using the response-transform object within stage-metadata. The CDN generates a synthetic response directly to the client without contacting the origin.

Example 1: Reject a Request

To reject a request, set the desired HTTP status code (e.g., "403") using response-transform.synthetic.response-status.

In this example, requests are rejected with a 403 Forbidden status if the MySecret header does not match the expected value.

The match field contains the MEL expression that sets the condition for rejecting the request.

{
"generic-metadata-type": "MI.ProcessingStages",
"generic-metadata-value": {
"client-request": [
{
"match": {
"expression": "req.h.MySecret != 'm1y2e3f4b5m6m7y9'"
},
"stage-metadata": [
{
"response-transform": {
"synthetic": {
"response-status": "403"
}
}
}
]
}
]
}
}


Example 2: Redirect a Request

Set the redirect status code (e.g., "301", "302") in response-transform.synthetic.response-status and add a Location header within response-transform.synthetic.headers specifying the redirect target URL. The target URL can be constructed dynamically using MEL expressions by setting value-is-expression to true.

This example redirects requests from a specific referrer (https://example.com) to https://the-other-server.com, preserving the original path and query string.

{
"generic-metadata-type": "MI.ProcessingStages",
"generic-metadata-value": {
"client-request": [
{
"match": {
"expression": "req.h.referer ~= 'https://example.com'"
},
"stage-metadata": [
{
"response-transform": {
"synthetic": {
"response-status": "301",
"headers": [
{
"name": "location",
"value": "'https://the-other-server.com' . req.uri.path . ((req.uri.query == '') ? '' : '?') . req.uri.query",
"value-is-expression": true
}
]
}
}
}
]
}
]
}
}


origin-request

This stage lets you modify the request before it is sent to the origin server. You can manipulate the request received from the client by modifying the URI value, or adding/replacing/deleting request headers. MEL expressions can be used to generate dynamic values for these fields, and to create match conditions.

These actions are defined within the request-transform object inside stage-metadata.

The origin-request stage supports the following actions within request-transform:

ActionDescription
URI Rewrite(uri, uri-is-expression)
Modifies the URI path and/or query string from the client before sending the request to the origin, often using a MEL expression.
Add Header(headers.add)
Adds the specified header/s and header value/s to the request, in addition to any same-name headers that may already be present.
Replace Header(headers.replace)
Replaces the header value for all instances of the header that are already present. If the header is not already in the request, this action adds the header and specified value to the request.
Delete Header(headers.delete)
Deletes all instances of the specified header/s from the request.
note

Actions within a single origin-request rule are executed in the order in which they appear, so it is important to arrange them in a logical sequence.

The exception is header transform actions—delete header, replace header, and add header— which are always executed in the fixed order: delete, then replace, then add, regardless of their placement within the rule.

To control the order of header transforms differently, define them in separate rules and arrange the rules accordingly.


Example 1: Add a Request Header

The following configuration adds the x-cdn header with the value qwilt to every origin request.

{
"generic-metadata-type": "MI.ProcessingStages",
"generic-metadata-value": {
"origin-request": [
{
"stage-metadata": [
{
"request-transform": {
"headers": {
"add": [
{
"value": "qwilt",
"name": "x-cdn",
"value-is-expression": false
}
]
}
}
}
]
}
]
}
}


Example 2: Replace a Header

Configure a replace rule to replace any existing value if the header is already present, or to add the header and specified value if the header is not already present.

{
"generic-metadata-type": "MI.ProcessingStages",
"generic-metadata-value": {
"origin-request": [
{
"stage-metadata": [
{
"request-transform": {
"headers": {
"replace": [
{
"value": "qwilt",
"name": "x-cdn"
}
]
}
}
}
]
}
]
}
}


Example 3: Delete a Header

Use delete to delete a header from the origin request:

{
"generic-metadata-type": "MI.ProcessingStages",
"generic-metadata-value": {
"origin-request": [
{
"stage-metadata": [
{
"request-transform": {
"headers": {
"delete": [
"x-forwarded-for"
]
}
}
}
]
}
]
}
}


Example 4: Add Header Constructed Based on a MEL Expression

Instead of setting a static header value, you can add a value construction expression to the configuration. To do so, add the "value-is-expression" attribute and use the "value" attribute to add the MEL expression.

{
"generic-metadata-type": "MI.ProcessingStages",
"generic-metadata-value": {
"origin-request": [
{
"stage-metadata": [
{
"request-transform": {
"headers": {
"add": [
{
"value": "<value construction expression>",
"name": "x-cdn",
"value-is-expression": true
}
]
}
}
}
]
}
]
}
}


Example 5: Add Header if Condition Defined by Match Expression is Met

To modify the origin request only under certain conditions, a match expression is added to the configuration:

{
"generic-metadata-type": "MI.ProcessingStages",
"generic-metadata-value": {
"origin-request": [
{
"stage-metadata": [
{
"request-transform": {
"headers": {
"add": [
{
"value": "qwilt",
"name": "x-cdn"
}
]
}
}
}
],
"match": {
"expression": "req.uri.query.foo == 'bar'"
}
}
]
}
}


Example 6: Rewrite the URI Path

To configure a URI manipulation, you set the MEL Expression in the uri field.

This example uses URI manipulation to remove the first path segment. For example, /session123/video/file.mp4 will be changed to /video/file.mp4.

{
"generic-metadata-type": "MI.ProcessingStages",
"generic-metadata-value": {
"origin-request": [
{
"stage-metadata": [
{
"request-transform": {
"uri": "match_replace(req.uri.path, '^/[^/]+(/.*)$', '$1') . ((req.uri.query == '') ? '' : '?') . req.uri.query",
"uri-is-expression": true
}
}
]
}
]
}
}


Example 7: Remove all Query Parameters

This is how you would instruct the CDN to remove all the query parameters but preserve the path:

{
"generic-metadata-type": "MI.ProcessingStages",
"generic-metadata-value": {
"origin-request": [
{
"stage-metadata": [
{
"request-transform": {
"uri": "req.uri.path",
"uri-is-expression": true
}
}
]
}
]
}
}


Example 8: Remove Query Parameters and Add Prefix to URI

This example removes all the query parameters and prepends the URI with the string, /video.

{
"generic-metadata-type": "MI.ProcessingStages",
"generic-metadata-value": {
"origin-request": [
{
"stage-metadata": [
{
"request-transform": {
"uri": "'/video' . req.uri.path",
"uri-is-expression": true
}
}
]
}
]
}
}


client-response

This stage lets you modify the client response received from the origin before it is sent to the client. Modifications can include overriding the HTTP status code or adding/replacing/deleting response headers.

These actions are defined within the response-transform object inside stage-metadata.

MEL expressions can be used to generate dynamic values for these fields, and to create match conditions.

The client-response object supports the following actions within response-transform:

ActionDescription
Status Code Override(response-status)
Sets the HTTP status code in the Client Response, overriding the status code received from the origin.
Add Header(headers.add)
Adds the specified header/s and header value/s to the response, in addition to any same-name headers that may already be present.
Replace Header(headers.replace)
Replaces the header value for all instances of the header that are already present. If the header is not already in the response, this action adds the header and specified value to the response.
Delete Header(headers.delete)
Deletes all instances of the specified header/s from the response.

In addition, you can add a MEL expression to create a match condition.

note

Actions within a single client-response rule are executed in the order in which they appear, so it is important to arrange them in a logical sequence.

The exception is header transform actions—delete header, replace header, and add header— which are always executed in the fixed order: delete, then replace, then add, regardless of their placement within the rule.

To control the order of header transforms differently, define them in separate rules and arrange the rules accordingly.


Example 1: Add a Response Header

This example instructs the CDN to add the served-by header with the value qwilt-cdn to every client response.

{
"generic-metadata-type": "MI.ProcessingStages",
"generic-metadata-value": {
"client-response": [
{
"stage-metadata": [
{
"response-transform": {
"headers": {
"add": [
{
"value": "qwilt-cdn",
"name": "served-by"
}
]
}
}
}
]
}
]
}
}


Note that this action defines a static value, "qwilt-cdn."


Example 2: Add a Dynamic Header

To set a dynamic header value with a MEL expression, add the value-is-expression attribute and use the value field to define the MEL expression:

{
"generic-metadata-type": "MI.ProcessingStages",
"generic-metadata-value": {
"origin-request": [
{
"stage-metadata": [
{
"response-transform": {
"headers": {
"add": [
{
"value": "<value construction expression>",
"name": "x-cdn",
"value-is-expression": true
}
]
}
}
}
]
}
]
}
}


Example 3: Replace Header

In this example, any instance of the x-cdn header in the client response is assigned the value, qwilt. If no instance of the header is found, the header is added to the response and assigned the value qwilt.

{
"generic-metadata-type": "MI.ProcessingStages",
"generic-metadata-value": {
"origin-request": [
{
"stage-metadata": [
{
"request-transform": {
"headers": {
"replace": [
{
"value": "qwilt",
"name": "x-cdn"
}
]
}
}
}
]
}
]
}
}


Example 4: Delete Header

This example is configured to delete the "server" header from the client response.

{
"generic-metadata-type": "MI.ProcessingStages",
"generic-metadata-value": {
"client-response": [
{
"stage-metadata": [
{
"response-transform": {
"headers": {
"delete": [
"server"
]
}
}
}
]
}
]
}
}


Example 5: Set a Match Condition

To modify the client response only under certain conditions, add a match expression to the configuration.

{
"generic-metadata-type": "MI.ProcessingStages",
"generic-metadata-value": {
"client-response": [
{
"stage-metadata": [
{
"response-transform": {
"headers": {
"add": [
{
"value": "qwilt",
"name": "served-by"
}
]
}
}
}
],
"match": {
"expression": "req.uri.query.foo == 'bar'"
}
}
]
}
}


Example 6: Override the Status Code

This example replaces the HTTP status code received from the origin with 200 OK.

{
"generic-metadata-type": "MI.ProcessingStages",
"generic-metadata-value": {
"client-response": [
{
"stage-metadata": [
{
"response-transform": {
"response-status": "200"
}
}
]
}
]
}
}